#include "ObjectSceneManager.h"


//====================================================== OBJECT SCENE MANAGER===
ObjectSceneManager* ObjectSceneManager::objSceneMgr = NULL;

ObjectSceneManager* ObjectSceneManager::getSingleton(void)
{
	if(objSceneMgr == NULL)
		objSceneMgr = new ObjectSceneManager();
	return objSceneMgr;
}

ObjectSceneManager::ObjectSceneManager()
{
	// Initialises scene manager
	m_Scenes.reserve(100);			// Reserve memory for scenes

	// Create default empty object scene. This scene will then be populated or replaced by other populated scene.
	//m_pCurrentScene = new ObjectScene("Default AGT Scene");

	// Create default ogre scene manager
	Ogre::Root *root = RenderManager::getSingleton()->getRoot();					// Get Ogre root from render manager
	m_pSceneMgr = root->createSceneManager(Ogre::ST_GENERIC, "Default AGT Scene");	// Set name and type of scene
	m_pCamera = m_pSceneMgr->createCamera("DefaultScene_Camera");					// Create camera
	m_pCamera->setNearClipDistance(1);												// Set the near clipping distance
	m_pCamera->lookAt(0,0,0);													// Set camera look at

	Ogre::RenderWindow* rw = RenderManager::getSingleton()->getRenderWindow();		// Get render window pointer
	m_pViewport = rw->addViewport(m_pCamera);										// Adds viewport to camera
	m_pViewport->setBackgroundColour(Ogre::ColourValue(0.0,0.0,0.0));				// Black default background

	// Calculate and set viewport size ratio
	m_pCamera->setAspectRatio( Ogre::Real(m_pViewport->getActualWidth()) / Ogre::Real(m_pViewport->getActualHeight()) );

	// Setup texture info
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_BILINEAR);
	Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(8);


	// Add this to the framelistener so that this can be updated
	root->addFrameListener(this);
}


ObjectSceneManager::~ObjectSceneManager()
{
}

// Private----
void ObjectSceneManager::setCameraViewport()
{
	Ogre::SceneManager* mgr = m_pCurrentScene->getOSceneMgr();
	if(!mgr->hasCamera(m_pCurrentScene->getName()+"_Camera"))
	{
		m_pCamera = mgr->createCamera(m_pCurrentScene->getName()+"_Camera");
		m_pCamera->setNearClipDistance(1);
		m_pCamera->lookAt(0,0,0);
	}
	else
	{
		m_pCamera = mgr->getCamera(m_pCurrentScene->getName()+"_Camera");
	}

	RenderManager::getSingleton()->getRenderWindow()->removeAllViewports();
	m_pViewport = RenderManager::getSingleton()->getRenderWindow()->addViewport(m_pCamera);
	m_pViewport->setBackgroundColour(Ogre::ColourValue(0.0,0.0,0.0));

	m_pCamera->setAspectRatio( Ogre::Real(m_pViewport->getActualWidth()) / Ogre::Real(m_pViewport->getActualHeight()) );

	// Setup texture info
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_BILINEAR);
	Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(8);
	
}


//void ObjectSceneManager::createScene(string scene_name)
//{
//	// Classes inherited from Scene class
//}


bool ObjectSceneManager::ManageScene(ObjectScene *scene)
{
	if(!isInStore(scene->getName()))
	{
		m_Scenes.push_back(scene);
		return true;
	}
	return false;
}

void ObjectSceneManager::switchToScene(string scene_name, Object* playerObj)
{
	for(it = m_Scenes.begin(); it != m_Scenes.end(); ++it)
	{
		if((*it)->getName() == scene_name)
		{
			m_pCurrentScene = (*it);
			setCameraViewport();
			if(playerObj != NULL)
			{
				m_pCurrentScene->getObjManager()->manageObject(playerObj);
			}
		}
	}
}

ObjectScene* ObjectSceneManager::getSceneOfObject(Object *obj)
{
	for(it = m_Scenes.begin(); it != m_Scenes.end(); ++it)
	{
		if( (*it)->getObjManager()->isObjectInStore(obj) )
		{
			return (*it);
		}
	}

	return NULL;
}

ObjectScene* ObjectSceneManager::getScene(string scene_name)
{
	for(it = m_Scenes.begin(); it != m_Scenes.end(); ++it)
	{
		if((*it)->getName() == scene_name)
		{
			return (*it);
		}
	}
	return NULL;
}

bool ObjectSceneManager::isInStore(string scene_name)
{
	for(it = m_Scenes.begin(); it != m_Scenes.end(); ++it)
	{
		if((*it)->getName() == scene_name)
		{
			return true;
		}
	}
	return false;
}

void ObjectSceneManager::addObjectToScene(string scene_name, Object* obj)
{
}

void ObjectSceneManager::removeObjectFromScene(ObjectScene *scene)
{
}


void ObjectSceneManager::updateScene()
{
	if(m_pCurrentScene != NULL)
	{
		m_pCurrentScene->update();
	}
}

// Replacement for the while loop. This function will be called by Ogre Framelistener when the 
// renderer is being updated
bool ObjectSceneManager::frameStarted(const Ogre::FrameEvent& evt)
{
	// ObjectSceneManager should not return a false and exit the application
	updateScene();

	return true;
}

bool ObjectSceneManager::frameEnded(const Ogre::FrameEvent& evt)
{
	return true;
}